/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package projetocompiladores;

import java.io.*;
import java.util.*;
import java.lang.*;

/**
 *
 * @author Nailton
 */
public class ProjetoCompiladores {

    /**
     * @param args the command line arguments
     */
    public static ArrayList<token> listaToken = new ArrayList<token>();
    public static String tokenCorrente = "";
    public static String reservadas[] = new String[50];
    public static File source;
    public static int posicao = 0;

    private static void inicializaReservadas() {

        reservadas[0] = "for";

    }

    public static void main(String[] args) {

        inicializaReservadas();
        BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in)); // cria um objeto pra ler o nome do arquivo
        System.out.println("Digite o caminho referente arquivo:");
        String caminho = "";
        try {
            caminho = buffer.readLine();
            Letexto(caminho);
        } catch (IOException e) {
        }

        for (int i = 0; i < listaToken.size(); i++) {
            listaToken.get(i).setTipo(reconhecedor(listaToken.get(i).getToken()));
        }

        imprimirTokens();

    }

    private static void imprimirTokens() {
        for (int i = 0; i < listaToken.size(); i++) {
            System.out.println("<" + listaToken.get(i).getToken() + "," + listaToken.get(i).getPosicao() + "," + listaToken.get(i).getTipo() + ">");

        }
    }

    public static void Letexto(String caminho) {

        BufferedReader br;
        String texto = "";

        try {

            source = new File(caminho); // pelo q eu entendi, cria um objeto que aponta para o arquivo que é especificado pelo caminho
            FileReader fr = new FileReader(source);  //objeto para ler o arquivo
            br = new BufferedReader(fr);   //objeto que trás o texto arquivo para o buffer, eu acho
            int s;
            //Nesse while ele vai ler o texto, linha por linha, até encontrar o fim 
            while ((s = br.read()) != -1) {
                //texto = texto + (char) s;
                char temp = (char) s;
                posicao = posicao + 1;
                //System.out.println(temp);
                scanSeparator(temp);
                continue;
            }
            //-----------------------------------------------------------------//
            //Fechando o ultimo token, armengagem, resolver depois, tenho que saber quando é o fim do arquivo, não sei como é
            listaToken.add(new token(posicao, tokenCorrente));
            tokenCorrente = "";
            //-----------------------------------------------------------------//
            

        } catch (IOException e) {
            //Tem que colocar, não conheço tratamento de excessão do Java(ainda).
        }
    }

    //-----------------------------------------------------------------//
    //Reconhecer letras, se for retorna verdadeiro
    public static boolean isLetter(char c) {
        return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
    }
    //-----------------------------------------------------------------//
    
    
    //-----------------------------------------------------------------//
    //Reconhecer digito, se for retorna verdadeiro
    public static boolean isDigit(char c) {
        return (c >= '0' && c <= '9');
    }
    
    //-----------------------------------------------------------------//
    //Reconhecer Parebteses,clchetes e chaves, se for retorna verdadeiro
    public static boolean isPCC(char c) {
        return (c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c == '}');
    }

    //-----------------------------------------------------------------//
    //Reconhecer operadores, se for retorna verdadeiro
    public static boolean isOperator(char c) {
        return (c == '+' || c == '-' || c == '*' || c == '/'
                || c == '=' || c == '<' || c == '>' || c == '\\'
                || c == '&' || c == '%' || c == '^'
                || c == '?');
    }

    //-----------------------------------------------------------------//
    //Essa funcao coloca os char na String temporária para formar um token
    public static void coloqueNoTokenCorrente(char currentChar, int resetar) {

        if (resetar == 1) {
            listaToken.add(new token(posicao, tokenCorrente));
            tokenCorrente = "";
            tokenCorrente = tokenCorrente + currentChar;
            listaToken.add(new token(posicao, tokenCorrente));
            tokenCorrente = "";
        } else {
            tokenCorrente = tokenCorrente + currentChar;
        }
        //System.out.println(tokenCorrente);
    }
    //-----------------------------------------------------------------//
    
    
    //-----------------------------------------------------------------//
    //Funcao que determina onde começa e termina um token
    public static void scanSeparator(char currentChar) {

        if (isOperator(currentChar) || currentChar == ' ' || currentChar == '\n' || isPCC(currentChar)) {
            coloqueNoTokenCorrente(currentChar, 1);
        } else {
            coloqueNoTokenCorrente(currentChar, 0);
        }

    }
    //-----------------------------------------------------------------//
    
    
    //-----------------------------------------------------------------//
    //Essa funcao recebe um token para definir o seu tipo
    public static String reconhecedor(String TipandoToken) {

        int i = 0;
        String Retorno = "";
        
        //-----------------------------------------------------------------//
        //Aqui imprime o erro atual, que alguns carcteres não são reconhecidos, ou seja vem vazio
        //System.out.println(TipandoToken.charAt(i));
        //-----------------------------------------------------------------//
        
        switch (TipandoToken.charAt(i)) {
            
            case 'a':  case 'b':  case 'c':  case 'd':  case 'e':
            case 'f':  case 'g':  case 'h':  case 'i':  case 'j':
            case 'k':  case 'l':  case 'm':  case 'n':  case 'o':
            case 'p':  case 'q':  case 'r':  case 's':  case 't':
            case 'u':  case 'v':  case 'w':  case 'x':  case 'y':
            case 'z':
            case 'A':  case 'B':  case 'C':  case 'D':  case 'E':
            case 'F':  case 'G':  case 'H':  case 'I':  case 'J':
            case 'K':  case 'L':  case 'M':  case 'N':  case 'O':
            case 'P':  case 'Q':  case 'R':  case 'S':  case 'T':
            case 'U':  case 'V':  case 'W':  case 'X':  case 'Y':
            case 'Z':
                //System.out.println("ENTROU EM SUB-ID");
                if (isLetter(TipandoToken.charAt(++i))) {
                    for (int j = ++i; i < TipandoToken.length(); i++) {
                        if (isLetter(TipandoToken.charAt(i)) || isDigit(TipandoToken.charAt(i)) || TipandoToken.charAt(i) == '_') {
                        } else {
                            return "ERROR";
                        }
                    }
                    return "SUB-ID";
                }
                return "SUB-ID"; 
            
            case ' ':
                return "DEMILITADOR";
                
            
            case '@':
                //System.out.println("ENTROU EM ARRAY");
                if (isLetter(TipandoToken.charAt(++i))) {
                    for (int j = ++i; i < TipandoToken.length(); i++) {
                        if (isLetter(TipandoToken.charAt(i)) || isDigit(TipandoToken.charAt(i)) || TipandoToken.charAt(i) == '_') {
                        } else {
                            return "ERROR";
                        }
                    }
                    return "ARRAY";
                }
                return "ERROR";
                
                
            case '$':
                //System.out.println("ENTROU EM IDENTIFICADOR");
                if (isLetter(TipandoToken.charAt(++i))) {
                    for (int j = ++i; i < TipandoToken.length(); i++) {
                        if (isLetter(TipandoToken.charAt(i)) || isDigit(TipandoToken.charAt(i)) || TipandoToken.charAt(i) == '_') {
                        } else {
                            return "ERROR";
                        }
                    }
                    return "IDENTIFICADOR";
                }
                return "ERROR";
                
            case '+':  case '-':  case '*': case '/':  case '=':
            case '<':  case '>':  case '\\':  case '&':
            case '%':  case '^':  case '?':
                //System.out.println("ENTROU AQUI EM OPERADOR");
                if(TipandoToken.length() == 2){
                    if((TipandoToken.charAt(i) == '=' && TipandoToken.charAt(++i) == '=') || (TipandoToken.charAt(i) == '+' && TipandoToken.charAt(++i) == '+') || (TipandoToken.charAt(i) == '-' && TipandoToken.charAt(++i) == '-')){
                        return "OPERADOR";
                    
                    }else{
                        return "ERROR";
                    }
                }
                return "OPERADOR";

            case '0':  case '1':  case '2':  case '3':  case '4':
            case '5':  case '6':  case '7':  case '8':  case '9':
                //System.out.println("ENTROU EM INTEIRO");
                for (int j = ++i; j < TipandoToken.length(); j++) {
                        if (isDigit(TipandoToken.charAt(j))) {
                        }else if(TipandoToken.charAt(j) == '.'){
                            if(++j < TipandoToken.length()){
                                if(isDigit(TipandoToken.charAt(++j))){
                                    Retorno = "FLOAT";
                                }else {
                                    return "ERROR";
                                }
                            }else{
                                return "ERROR";
                            }
                        }
                    }
                    if(Retorno.contains("FLOAT")){
                        return "FLOAT";
                    }
                    return "INTEIRO";
            
            case '"':
                //System.out.println("ENTROU EM STRING");
                if(TipandoToken.charAt(TipandoToken.length()-1) == '"'){
                    return "STRING";
                }
                return "ERROR";
                
                
                
            case '(':
                return "EPARENTESE";

            case ')':
                return "DPARENTESE";

            case '[':
                return "ECOLCHETES";

            case ']':
                return "DCOLCHETES";

            case '{':
                return "ECHAVES";

            case '}':
                return "DCHAVES";   
        }
        //System.out.println("FIM DO TOKEN");
        
        
        
        return "ERROR";


    }
}
//-----------------------------------------------------------------//